use crate::error::TauriCommandError;
use crate::types::{
    LspServerId, CompletionList, CompletionItem, CompletionItemKind,
    Hover, Location, DocumentSymbol, SymbolKind, Position, Range
};
use codegraph_lsp::{LspServerManager, LspManagerConfig, LspServerStatus as ManagerStatus, ResourceStats};
use dashmap::DashMap;
use std::sync::Arc;
use std::collections::HashMap;
use tokio::sync::OnceCell;

/// LSP 服务器信息
#[derive(Debug, Clone)]
pub struct LspServerInfo {
    pub id: String,
    pub language: String,
    pub status: LspServerStatus,
    pub started_at: chrono::DateTime<chrono::Utc>,
    pub last_activity: chrono::DateTime<chrono::Utc>,
    pub resource_stats: Option<ResourceStats>,
}

#[derive(Debug, Clone)]
pub enum LspServerStatus {
    NotStarted,
    Starting,
    Running,
    Stopping,
    Stopped,
    Error(String),
    Crashed,
}

impl From<ManagerStatus> for LspServerStatus {
    fn from(status: ManagerStatus) -> Self {
        match status {
            ManagerStatus::NotStarted => LspServerStatus::NotStarted,
            ManagerStatus::Starting => LspServerStatus::Starting,
            ManagerStatus::Running => LspServerStatus::Running,
            ManagerStatus::Stopping => LspServerStatus::Stopping,
            ManagerStatus::Stopped => LspServerStatus::Stopped,
            ManagerStatus::Error(msg) => LspServerStatus::Error(msg),
            ManagerStatus::Crashed => LspServerStatus::Crashed,
        }
    }
}

// 全局LSP管理器实例
static LSP_MANAGER: OnceCell<Arc<LspServerManager>> = OnceCell::const_new();

/// LSP 服务
pub struct LspService {
    servers: Arc<DashMap<String, LspServerInfo>>,
}

impl LspService {
    /// 创建新的 LSP 服务实例
    pub fn new() -> Self {
        Self {
            servers: Arc::new(DashMap::new()),
        }
    }

    /// 初始化LSP管理器
    pub async fn initialize_manager() -> Result<(), TauriCommandError> {
        let config = LspManagerConfig::default();
        let manager = Arc::new(LspServerManager::new(config));

        if let Err(_) = LSP_MANAGER.set(manager.clone()) {
            return Err(TauriCommandError::lsp("LSP管理器已经初始化"));
        }

        manager.start().await
            .map_err(|e| TauriCommandError::lsp(&format!("启动LSP管理器失败: {}", e)))?;

        log::info!("LSP管理器初始化成功");
        Ok(())
    }

    /// 获取LSP管理器实例
    async fn get_manager() -> Result<Arc<LspServerManager>, TauriCommandError> {
        LSP_MANAGER.get()
            .ok_or_else(|| TauriCommandError::lsp("LSP管理器未初始化"))
            .map(|manager| manager.clone())
    }
    
    /// 启动 LSP 服务器
    pub async fn start_server(language: &str) -> Result<LspServerId, TauriCommandError> {
        log::info!("Starting LSP server for language: {}", language);

        let manager = Self::get_manager().await?;

        // 使用新的管理器启动服务器
        let server_id = manager.start_server(language).await
            .map_err(|e| TauriCommandError::lsp(&format!("启动LSP服务器失败: {}", e)))?;

        // 更新本地缓存
        let now = chrono::Utc::now();
        let server_info = LspServerInfo {
            id: server_id.clone(),
            language: language.to_string(),
            status: LspServerStatus::Running,
            started_at: now,
            last_activity: now,
            resource_stats: None,
        };

        LSP_SERVICE.servers.insert(language.to_string(), server_info);

        log::info!("LSP server started successfully: {}", server_id);
        Ok(LspServerId(server_id))
    }
    
    /// 停止 LSP 服务器
    pub async fn stop_server(server_id: LspServerId) -> Result<String, TauriCommandError> {
        log::info!("Stopping LSP server: {}", server_id.0);

        let manager = Self::get_manager().await?;

        // 查找服务器对应的语言
        let language = {
            let servers = LSP_SERVICE.servers.clone();
            let mut found_language = None;
            for entry in servers.iter() {
                if entry.value().id == server_id.0 {
                    found_language = Some(entry.key().clone());
                    break;
                }
            }
            found_language.ok_or_else(|| TauriCommandError::lsp("LSP 服务器不存在"))?
        };

        // 使用管理器停止服务器
        manager.stop_server(&language).await
            .map_err(|e| TauriCommandError::lsp(&format!("停止LSP服务器失败: {}", e)))?;

        // 从本地缓存移除
        LSP_SERVICE.servers.remove(&language);

        log::info!("LSP server stopped successfully");
        Ok("LSP 服务器已停止".to_string())
    }
    
    /// 获取自动完成
    pub async fn get_completion(
        file_path: &str,
        position: Position,
        language: &str,
    ) -> Result<CompletionList, TauriCommandError> {
        Self::ensure_server_running(language).await?;
        
        // 模拟自动完成结果
        let items = vec![
            CompletionItem {
                label: "function".to_string(),
                kind: Some(CompletionItemKind::Function),
                detail: Some("Function declaration".to_string()),
                documentation: Some("Creates a new function".to_string()),
                insert_text: Some("function ${1:name}(${2:params}) {\n\t${3:body}\n}".to_string()),
                sort_text: Some("0001".to_string()),
                filter_text: Some("function".to_string()),
            },
            CompletionItem {
                label: "variable".to_string(),
                kind: Some(CompletionItemKind::Variable),
                detail: Some("Variable declaration".to_string()),
                documentation: Some("Creates a new variable".to_string()),
                insert_text: Some("let ${1:name} = ${2:value};".to_string()),
                sort_text: Some("0002".to_string()),
                filter_text: Some("variable".to_string()),
            },
        ];
        
        Self::update_server_activity(language).await;
        
        Ok(CompletionList {
            is_incomplete: false,
            items,
        })
    }
    
    /// 获取悬停信息
    pub async fn get_hover(
        file_path: &str,
        position: Position,
        language: &str,
    ) -> Result<Option<Hover>, TauriCommandError> {
        Self::ensure_server_running(language).await?;
        
        // 模拟悬停信息
        let hover = Hover {
            contents: "**function** `example(param: string): void`\n\nThis is an example function.".to_string(),
            range: Some(Range {
                start: position,
                end: Position { row: position.row, column: position.column + 7 },
            }),
        };
        
        Self::update_server_activity(language).await;
        
        Ok(Some(hover))
    }
    
    /// 获取定义位置
    pub async fn get_definition(
        file_path: &str,
        position: Position,
        language: &str,
    ) -> Result<Vec<Location>, TauriCommandError> {
        Self::ensure_server_running(language).await?;
        
        // 模拟定义位置
        let locations = vec![
            Location {
                uri: format!("file://{}", file_path),
                range: Range {
                    start: Position { row: 10, column: 0 },
                    end: Position { row: 10, column: 20 },
                },
            }
        ];
        
        Self::update_server_activity(language).await;
        
        Ok(locations)
    }
    
    /// 获取引用位置
    pub async fn get_references(
        file_path: &str,
        position: Position,
        language: &str,
        include_declaration: bool,
    ) -> Result<Vec<Location>, TauriCommandError> {
        Self::ensure_server_running(language).await?;
        
        // 模拟引用位置
        let mut locations = vec![
            Location {
                uri: format!("file://{}", file_path),
                range: Range {
                    start: Position { row: 15, column: 5 },
                    end: Position { row: 15, column: 15 },
                },
            },
            Location {
                uri: format!("file://{}", file_path),
                range: Range {
                    start: Position { row: 20, column: 10 },
                    end: Position { row: 20, column: 20 },
                },
            },
        ];
        
        if include_declaration {
            locations.push(Location {
                uri: format!("file://{}", file_path),
                range: Range {
                    start: Position { row: 10, column: 0 },
                    end: Position { row: 10, column: 20 },
                },
            });
        }
        
        Self::update_server_activity(language).await;
        
        Ok(locations)
    }
    
    /// 获取文档符号
    pub async fn get_document_symbols(
        file_path: &str,
        language: &str,
    ) -> Result<Vec<DocumentSymbol>, TauriCommandError> {
        Self::ensure_server_running(language).await?;
        
        // 模拟文档符号
        let symbols = vec![
            DocumentSymbol {
                name: "main".to_string(),
                detail: Some("function".to_string()),
                kind: SymbolKind::Function,
                range: Range {
                    start: Position { row: 0, column: 0 },
                    end: Position { row: 10, column: 0 },
                },
                selection_range: Range {
                    start: Position { row: 0, column: 0 },
                    end: Position { row: 0, column: 4 },
                },
                children: None,
            },
        ];
        
        Self::update_server_activity(language).await;
        
        Ok(symbols)
    }
    
    /// 获取工作区符号
    pub async fn get_workspace_symbols(
        query: &str,
        language: &str,
    ) -> Result<Vec<DocumentSymbol>, TauriCommandError> {
        Self::ensure_server_running(language).await?;
        
        // 模拟工作区符号搜索
        let symbols = vec![];
        
        Self::update_server_activity(language).await;
        
        Ok(symbols)
    }
    
    /// 格式化文档
    pub async fn format_document(
        file_path: &str,
        language: &str,
    ) -> Result<String, TauriCommandError> {
        Self::ensure_server_running(language).await?;
        
        // 模拟文档格式化
        let formatted_content = std::fs::read_to_string(file_path)
            .map_err(|e| TauriCommandError::io(e.to_string()))?;
        
        Self::update_server_activity(language).await;
        
        Ok(formatted_content)
    }
    
    /// 获取诊断信息
    pub async fn get_diagnostics(
        file_path: &str,
        language: &str,
    ) -> Result<serde_json::Value, TauriCommandError> {
        Self::ensure_server_running(language).await?;
        
        // 模拟诊断信息
        let diagnostics = serde_json::json!([
            {
                "range": {
                    "start": { "row": 5, "column": 10 },
                    "end": { "row": 5, "column": 20 }
                },
                "severity": 1,
                "message": "Unused variable",
                "source": "rust-analyzer"
            }
        ]);
        
        Self::update_server_activity(language).await;
        
        Ok(diagnostics)
    }
    
    /// 获取服务器状态
    pub async fn get_server_status() -> Result<serde_json::Value, TauriCommandError> {
        let mut servers = HashMap::new();
        
        for entry in LSP_SERVICE.servers.iter() {
            let (language, server) = entry.pair();
            servers.insert(language.clone(), serde_json::json!({
                "id": server.id,
                "language": server.language,
                "status": format!("{:?}", server.status),
                "started_at": server.started_at,
                "last_activity": server.last_activity,
            }));
        }
        
        Ok(serde_json::json!({
            "servers": servers,
            "total_servers": LSP_SERVICE.servers.len(),
        }))
    }
    
    /// 重启服务器
    pub async fn restart_server(language: &str) -> Result<LspServerId, TauriCommandError> {
        log::info!("Restarting LSP server for language: {}", language);

        let manager = Self::get_manager().await?;

        // 使用管理器重启服务器
        let server_id = manager.restart_server(language).await
            .map_err(|e| TauriCommandError::lsp(&format!("重启LSP服务器失败: {}", e)))?;

        // 更新本地缓存
        let now = chrono::Utc::now();
        let server_info = LspServerInfo {
            id: server_id.clone(),
            language: language.to_string(),
            status: LspServerStatus::Running,
            started_at: now,
            last_activity: now,
            resource_stats: None,
        };

        LSP_SERVICE.servers.insert(language.to_string(), server_info);

        log::info!("LSP server restarted successfully: {}", server_id);
        Ok(LspServerId(server_id))
    }

    /// 获取所有服务器状态
    pub async fn get_all_servers_status() -> Result<HashMap<String, LspServerStatus>, TauriCommandError> {
        let manager = Self::get_manager().await?;
        let status_map = manager.get_all_server_status().await;

        let result = status_map.into_iter()
            .map(|(lang, status)| (lang, status.into()))
            .collect();

        Ok(result)
    }

    /// 获取服务器资源统计
    pub async fn get_server_resource_stats(language: &str) -> Result<Option<ResourceStats>, TauriCommandError> {
        let manager = Self::get_manager().await?;
        let stats = manager.get_server_stats(language).await;
        Ok(stats)
    }

    /// 发现适合文件的LSP服务器
    pub async fn discover_server_for_file(file_path: &str) -> Result<Option<String>, TauriCommandError> {
        let manager = Self::get_manager().await?;
        let language = manager.discover_server_for_file(file_path).await;
        Ok(language)
    }

    /// 自动启动文件对应的LSP服务器
    pub async fn auto_start_server_for_file(file_path: &str) -> Result<Option<LspServerId>, TauriCommandError> {
        if let Some(language) = Self::discover_server_for_file(file_path).await? {
            let server_id = Self::start_server(&language).await?;
            Ok(Some(server_id))
        } else {
            Ok(None)
        }
    }
    
    // 私有辅助方法
    
    async fn ensure_server_running(language: &str) -> Result<(), TauriCommandError> {
        if let Some(server) = LSP_SERVICE.servers.get(language) {
            if matches!(server.status, LspServerStatus::Running) {
                return Ok(());
            }
        }
        
        // 自动启动服务器
        Self::start_server(language).await?;
        Ok(())
    }
    
    async fn update_server_activity(language: &str) {
        if let Some(mut server) = LSP_SERVICE.servers.get_mut(language) {
            server.last_activity = chrono::Utc::now();
        }
    }
}

impl Default for LspService {
    fn default() -> Self {
        Self::new()
    }
}

// 全局 LSP 服务实例
lazy_static::lazy_static! {
    pub static ref LSP_SERVICE: LspService = LspService::new();
}
